/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.game.math.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Observable;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.game.math.expression.Operator;

/**
 *
 * @author nmduc
 */
public class Configure extends Observable {

    public static final String SIGN = "sign";
    public static final String NUM_LENGTH = "num.length";
    public static final String NUM_EXPRESSION = "num.expression";
    public static final String NUM_OPERATOR = "num.operator";
    private static final String OPERATORS = "operators";
    private static final String MULTIPLIED_TABLE = "mult.table";
    private static final String MULTIPLIED_NUMBER = "mult.number";
    private static Configure configure;
    private static final String CONFIG_FILE_NAME = "config.properties";
    private Set<Operator> operators;
    private Properties properties;
    private Properties temProperties;
    private Configure() {
        this.properties = new Properties();
        try {
            File f = new File(CONFIG_FILE_NAME);
            if (f.exists()) {
                properties.load(new FileInputStream(f));
            }
        } catch (IOException ex) {
            Logger.getLogger(Configure.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (this.properties.getProperty(SIGN) == null) {
                this.properties.setProperty(SIGN, "false");
            }
            if (this.properties.getProperty(NUM_LENGTH) == null) {
                this.properties.setProperty(NUM_LENGTH, "1");
            }
            if (this.properties.getProperty(NUM_EXPRESSION) == null) {
                properties.setProperty(NUM_EXPRESSION, "10");
            }
            if (this.properties.getProperty(NUM_OPERATOR) == null) {
                this.properties.setProperty(NUM_OPERATOR, "1");
            }
            if (this.properties.getProperty(OPERATORS) == null) {
                this.properties.setProperty(OPERATORS, Operator.ADD.name());
            }
            if (this.properties.getProperty(MULTIPLIED_TABLE) == null) {
                this.properties.setProperty(MULTIPLIED_TABLE, "false");
            }
            if (this.properties.getProperty(MULTIPLIED_NUMBER) == null) {
                this.properties.setProperty(MULTIPLIED_NUMBER, "1");
            }
            operators = EnumSet.noneOf(Operator.class);
            String currentOperators = this.properties.getProperty(OPERATORS);
            String[] operatorNames = currentOperators.split("\\|");
            for (String operatorName : operatorNames) {
                if (!operatorName.isEmpty()) {
                    operators.add(Operator.valueOf(operatorName));
                }
            }
        }
    }

    public static Configure getInstance() {
        if (configure == null) {
            configure = new Configure();
        }
        return configure;
    }

    public void save() {
        try {
            //Store operator list to String
            StringBuilder operatorString = new StringBuilder();
            for (Operator operator : operators) {
                operatorString.append(operator.name()).append("|");
            }
            this.properties.setProperty(OPERATORS, operatorString.toString());
            this.properties.store(new FileOutputStream(CONFIG_FILE_NAME), "");
        } catch (IOException ex) {
            Logger.getLogger(Configure.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getProperty(String key) {
        return this.properties.getProperty(key);
    }

    public Object setProperty(String key, String value) {
        return this.properties.setProperty(key, value);
    }

    public void addOperator(Operator operator) {
        operators.add(operator);
        this.setChanged();
        this.notifyObservers();
    }

    public void removeOperator(Operator operator) {
        operators.remove(operator);
        this.setChanged();
        this.notifyObservers();
    }

    public Set<Operator> getOperators() {
        return operators;
    }

    public boolean isChosenMultiTable() {
        return Boolean.parseBoolean(this.getProperty(MULTIPLIED_TABLE));
    }

    public void setChosenMultiTable(boolean choosen, int multipliedNumber) {
        this.properties.setProperty(MULTIPLIED_TABLE, Boolean.toString(choosen));
        this.properties.setProperty(MULTIPLIED_NUMBER, Integer.toString(multipliedNumber));
        this.setChanged();
        this.notifyObservers();
    }

    public int getChosenMultiNumber() {
        return Integer.parseInt(this.properties.getProperty(MULTIPLIED_NUMBER));
    }

    public void initializeTempProperties() {
        this.temProperties = (Properties) this.properties.clone();
    }

    public Properties getTempProperties() {
        return this.temProperties;
    }

    public void removeTempProperties() {
        this.temProperties = null;
    }

    public void updateByTempProperties() {
        if (this.temProperties != null) {
            this.properties.clear();
            this.properties.putAll(this.temProperties);
        } else {
            throw new NullPointerException("temProperties is not initialized yet.");
        }
    }
}
